# 数据校验
import json
from datetime import datetime

from django.conf import settings
from django.db.transaction import atomic

from luckin.models import User, VerifyCode
from luckin.init_constant import (
    USER_LOGIN_PARAM_FORMAT,
    USER_REGISTER_PARAM_FORMAT
)
from luckin.form import RegisterForm, LoginForm, UpdateUserForm
from luckin.common import (
    valid_request_param,
    valid_request_data,
    get_timer,
    finally_encrypt_password,
    is_phone,
    random_verify_code,
    generate_captcha
)


# 登录验证
def handle_login(request, *args, **kwargs):
    # _q : {"account":"%s","password":"%s","code":"%s"}
    # 第一次根据用户传来的参数，进行数据校验
    if not valid_request_param(request):
        return False, "参数错误"

    # 走到这里代表，_q,_s参数合法，并且存在
    _q = request.data.get("_q")
    _s = request.data.get("_s")

    param_dict = json.loads(_q)
    forms = LoginForm(param_dict)

    # 检测_q参数是否合法
    if forms.is_valid():
        account = forms.cleaned_data.get("account").strip()
        password = forms.cleaned_data.get("password").strip()
        code = forms.cleaned_data.get("code").strip()

        # 第二次自己格式化数据验证
        _q_data = USER_LOGIN_PARAM_FORMAT % (account, password, code)
        user_agent = request.META.get("HTTP_USER_AGENT", "")
        path = request.path or ""
        if not valid_request_data(_q_data, _s, user_agent, path):
            return False, "参数错误"

        # 验证验证码是否正确
        flag, data = valid_verify_code(account, code)
        if not flag:
            return False, data
        # 验证用户是否存在
        user = User.objects.filter(phone=account, password=finally_encrypt_password(password)).first()
        if not user:
            return False, "手机号或密码错误"
        # 更改验证码使用状态
        data.is_use = 2
        data.save()
        return True, user
    else:
        return False, "提交数据不合法"


# 注册验证
def handle_register(request, *args, **kwargs):
    # _q:{"account":"%s","password":"%s","re_password":"%s","code":"%s"}
    # 第一次根据用户传来的参数，进行数据校验
    if not valid_request_param(request):
        return False, "参数错误"

    _q = request.data.get("_q")
    _s = request.data.get("_s")

    param_dict = json.loads(_q)
    forms = RegisterForm(param_dict)

    # 检测_q参数是否合法
    if forms.is_valid():
        account = forms.cleaned_data.get("account", "").strip()
        password = forms.cleaned_data.get("password", "").strip()
        re_password = forms.cleaned_data.get("re_password", "").strip()
        code = forms.cleaned_data.get("code", "").strip()

        # 第二次自己格式化数据验证
        _q_data = USER_REGISTER_PARAM_FORMAT % (account, password, re_password, code)
        user_agent = request.META.get("HTTP_USER_AGENT", "")
        path = request.path or ""
        if not valid_request_data(_q_data, _s, user_agent, path):
            return False, "参数错误"

        # 验证验证码是否正确
        flag, msg = valid_verify_code(account, code)
        if not flag:
            return False, msg
        # 检测用户是否已经存在
        user = User.objects.filter(phone=account).first()
        if user:
            return False, "该用户已存在"

        # 实现注册功能
        with atomic():
            # 创建用户
            user = User.objects.create(nickname=account, phone=account, password=finally_encrypt_password(password))
            # 更改验证码使用状态
            VerifyCode.objects.filter(phone=account).update(is_use=2)
            return True, user
    else:
        error_key = list(forms.errors)[0]
        error_msg = str(forms.errors.get(error_key))
        return False, error_msg


# 验证码是否正确，过期
def valid_verify_code(account, verify_code):
    verify_code_obj = VerifyCode.objects.filter(phone=account, verify_code=verify_code, is_use=1).first()
    if not verify_code_obj:
        return False, "验证码错误"
    timer = get_timer(verify_code_obj.update_time)
    if timer.seconds > settings.VERIFY_CODE_TIME_OUT:
        return False, "验证码已失效"
    return True, verify_code_obj


# 获取验证码
def handle_verify_code(request):
    # _q : {"account":%s}
    if not valid_request_param(request):
        return False, "参数错误"

    _q = request.data.get("_q")
    _s = request.data.get("_s")

    # 对_q参数进行校验
    param_dict = json.loads(_q)
    account = param_dict.get("account")
    if not isinstance(account, int):
        return False, "参数非法"

    if not is_phone(str(account)):
        return False, "手机号格式错误"

    # 生成验证码
    code = random_verify_code()
    print("验证码为:", code)

    # 判断该手机是否有记录，并且看看更新时间是否超过120s
    # 因为注册和登录功能都有验证码，所以不判断手机号是否存在于User表中
    verify_code_obj = VerifyCode.objects.filter(phone=account).first()
    if not verify_code_obj:
        # 创建图片
        picture_path = generate_captcha(code)
        VerifyCode.objects.create(phone=account, verify_code=code, picture_path=picture_path)
        return True, picture_path
    else:
        timer = get_timer(verify_code_obj.update_time)
        # 如果该验证码已经使用过了，就无需判断在规定时间不能重复发送验证码了
        if verify_code_obj.is_use == 1 and timer.seconds < settings.VERIFY_CODE_TIME_INTERVAL:
            return False, "%s秒内不错重复发送" % settings.VERIFY_CODE_TIME_INTERVAL
        else:
            picture_path = generate_captcha(code)
            verify_code_obj.verify_code = code
            verify_code_obj.is_use = 1
            verify_code_obj.picture_path = picture_path
            verify_code_obj.update_time = datetime.now()
            verify_code_obj.save()
            return True, picture_path


# 处理更新用户服务
def handle_update_user(request, *args, **kwargs):
    # _q : {"nickname":"%s","gender":"%s"}
    if not valid_request_param(request):
        return False

    _q = request.data.get("_q")
    _s = request.data.get("_s")

    param_dict = json.loads(_q)
    user_id = request.user.id
    form = UpdateUserForm(param_dict)

    # _q参数校验
    if form.is_valid():
        clean_data = dict()
        for key, value in form.cleaned_data.items():
            if value:
                clean_data[key] = value
        User.objects.filter(pk=user_id).update(**clean_data)
        return True
    return False


# 处理头像上传
def handle_user_avatar(request):
    if not valid_request_param(request):
        return False, "参数错误"

    # 这里_q为一个json格式的空字典，所以不做操作
    file = request.data.get("user_avatar")
    if not file:
        return False, "参数错误"
    file_name = file.name
    suffix = file_name.split(".")[-1]
    if suffix.upper() not in ["JPG", "PNG", "JPEG"]:
        return False, "文件格式错误"
    user_id = request.user.id
    user = User.objects.filter(pk=user_id).first()
    user.avatar = file
    user.save()
    return True, "media/" + user.avatar.name
